package editorarquivobmg.service;

import editorarquivobmg.codificacao.ICodificacao;
import editorarquivobmg.gui.TelaPrincipal;
import editorarquivobmg.model.BmgFile;
import editorarquivobmg.model.Texto;
import editorarquivobmg.util.ConversorTexto;
import editorarquivobmg.util.ManipuladorDados;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;

public class ManipuladorArquivoService {

    private File diretorioCorrente = null;
    private String arquivoPropriedade = "";

    public ManipuladorArquivoService(String arquivoPropriedade) throws Exception {
        this.arquivoPropriedade = arquivoPropriedade;
        definirEGravarDiretorioCorrente();
    }

    private void definirEGravarDiretorioCorrente() throws Exception {
        File retorno = new File(System.getProperty("user.home"));
        File arquivo = new File(arquivoPropriedade);
        if (arquivo.exists()) {
            Scanner sc = new Scanner(arquivo);
            if (sc.hasNextLine()) {
                String caminho = sc.nextLine();
                arquivo = new File(caminho);
                if (arquivo.exists()) {
                    retorno = arquivo;
                } else {
                    escreverArquivoConfigIni(System.getProperty("user.home"));
                }
            } else {
                escreverArquivoConfigIni(System.getProperty("user.home"));
            }
        } else {
            escreverArquivoConfigIni(System.getProperty("user.home"));
        }
        diretorioCorrente = retorno;
    }

    private void escreverArquivoConfigIni(String caminho) throws Exception {
        BufferedWriter fr = new BufferedWriter(new FileWriter(arquivoPropriedade));
        fr.write(caminho);
        fr.flush();
        fr.close();
    }

    public File abrirArquivoBMG(TelaPrincipal form) throws Exception {
        File arquivo = null;
        FileFilter bmgFileFilter = new FileFilter() {
            @Override
            public boolean accept(File file) {
                return file.getAbsolutePath().endsWith(".bmg") || file.isDirectory();
            }

            @Override
            public String getDescription() {
                return "Arquivos BMG";
            }
        };
        JFileChooser arquivoEscolhido = new JFileChooser(diretorioCorrente);
        arquivoEscolhido.setDialogTitle("Abrir Aqruivo BMG");
        arquivoEscolhido.setFileFilter(bmgFileFilter);

        int returnVal = arquivoEscolhido.showOpenDialog(form);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            verificarBmgFile(ManipuladorDados.obterBytes(arquivoEscolhido.getSelectedFile()));
            arquivo = arquivoEscolhido.getSelectedFile();
            diretorioCorrente = arquivoEscolhido.getCurrentDirectory();
            escreverArquivoConfigIni(diretorioCorrente.getAbsolutePath());
            System.out.println("Arquivo BMG aberto: " + arquivoEscolhido.getSelectedFile().getAbsolutePath());
        } else {
            throw new Exception("Operação de Abrir Arquivo BMG abortada.");
        }
        return arquivo;
    }

    private void verificarBmgFile(byte[] data) throws Exception {
        byte[] temp = new byte[8];
        String str;
        for (int i = 0; i < 8; i++) {
            temp[i] = data[i];
        }
        str = new String(temp, "UTF-8");
        if (!str.equals("MESGbmg1")) {
            throw new Exception("O arquivo não é um BMG File válido!");
        }
    }

    public File abrirArquivoMapeamento(TelaPrincipal form) throws Exception {
        File arquivo = null;
        FileFilter bmgFileFilter = new FileFilter() {
            @Override
            public boolean accept(File file) {
                return file.getAbsolutePath().endsWith(".bmap") || file.isDirectory();
            }

            @Override
            public String getDescription() {
                return "Arquivo de Mapeamento";
            }
        };
        JFileChooser arquivoEscolhido = new JFileChooser(diretorioCorrente);
        arquivoEscolhido.setDialogTitle("Abrir Aqruivo de Mapeamento");
        arquivoEscolhido.setFileFilter(bmgFileFilter);

        int returnVal = arquivoEscolhido.showOpenDialog(form);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            arquivo = arquivoEscolhido.getSelectedFile();
            diretorioCorrente = arquivoEscolhido.getCurrentDirectory();
            escreverArquivoConfigIni(diretorioCorrente.getAbsolutePath());
            System.out.println("Arquivo de Mapeamento aberto: " + arquivoEscolhido.getSelectedFile().getAbsolutePath());
        } else {
            throw new Exception("Operação de Abrir Arquivo de Mapeamento abortada.");
        }
        return arquivo;
    }

    public File abrirArquivoPixels(TelaPrincipal form) throws Exception {
        File arquivo = null;
        FileFilter bmgFileFilter = new FileFilter() {
            @Override
            public boolean accept(File file) {
                return file.getAbsolutePath().endsWith(".pixel") || file.isDirectory();
            }

            @Override
            public String getDescription() {
                return "Arquivo de Pixels";
            }
        };
        JFileChooser arquivoEscolhido = new JFileChooser(diretorioCorrente);
        arquivoEscolhido.setDialogTitle("Abrir Aqruivo de Pixels");
        arquivoEscolhido.setFileFilter(bmgFileFilter);

        int returnVal = arquivoEscolhido.showOpenDialog(form);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            arquivo = arquivoEscolhido.getSelectedFile();
            diretorioCorrente = arquivoEscolhido.getCurrentDirectory();
            escreverArquivoConfigIni(diretorioCorrente.getAbsolutePath());
            System.out.println("Arquivo de Pixel aberto: " + arquivoEscolhido.getSelectedFile().getAbsolutePath());
        } else {
            throw new Exception("Operação de Abrir Arquivo de Pixels abortada.");
        }
        return arquivo;
    }

    public void extrairScript(TelaPrincipal form, ConversorTexto parser, ArrayList<Texto> textos, ICodificacao codificacao) throws Exception {
        String str = "";
        JFileChooser arquivoEscolhido = new JFileChooser(diretorioCorrente) {
            @Override
            public void approveSelection() {
                File file = getSelectedFile();
                if (file.exists()) {
                    String msg = "\"{0}\" já existe.\nDeseja substituí-lo?";
                    msg = MessageFormat.format(msg, new Object[]{file.getName()});
                    String title = "Confirmar Salvar como";
                    int option = JOptionPane.showConfirmDialog(this, msg, title, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
                    if (option == JOptionPane.NO_OPTION) {
                        return;
                    }
                }
                super.approveSelection();
            }
        };

        arquivoEscolhido.setFileFilter(new FileNameExtensionFilter("Arquivo de Texto (*.txt)", "txt"));
        arquivoEscolhido.setDialogTitle("Extrair Script");

        int returnVal = arquivoEscolhido.showSaveDialog(form);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            for (int i = 0; i < textos.size(); i++) {
                str += (i + 1) + "############\n" + parser.parseOutAllCodes(new String(textos.get(i).getData(), codificacao.getCodificacao())) + "\n############";
            }
            byte[] x = ManipuladorDados.hexStringToByteArray(codificacao.getHexRepresentacao());
            byte[] y = str.getBytes(codificacao.getCodificacao());
            byte[] z = new byte[x.length + y.length];
            System.arraycopy(x, 0, z, 0, x.length);
            System.arraycopy(y, 0, z, x.length, y.length);
            FileOutputStream in = new FileOutputStream(arquivoEscolhido.getSelectedFile());
            in.write(z);
            in.close();
            diretorioCorrente = arquivoEscolhido.getCurrentDirectory();
            escreverArquivoConfigIni(diretorioCorrente.getAbsolutePath());
            System.out.println("Script extraído para o arquivo: " + arquivoEscolhido.getSelectedFile().getAbsolutePath());
        } else {
            throw new Exception("Operação de Extrair Script abortada.");
        }
    }

    public void extrairScript(TelaPrincipal form, ArrayList<Texto> textos, ICodificacao codificacao) throws Exception {
        String str = "";
        JFileChooser arquivoEscolhido = new JFileChooser(diretorioCorrente) {
            @Override
            public void approveSelection() {
                File f = getSelectedFile();
                if (f.exists()) {
                    String msg = "\"{0}\" já existe.\nDeseja substituí-lo?";
                    msg = MessageFormat.format(msg, new Object[]{f.getName()});
                    String title = "Confirmar Salvar como";
                    int option = JOptionPane.showConfirmDialog(this, msg, title, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
                    if (option == JOptionPane.NO_OPTION) {
                        return;
                    }
                }
                super.approveSelection();
            }
        };
        arquivoEscolhido.setFileFilter(new FileNameExtensionFilter("Arquivo de Texto (*.txt)", "txt"));
        arquivoEscolhido.setDialogTitle("Extrair Script");
        int returnVal = arquivoEscolhido.showSaveDialog(form);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            for (int i = 0; i < textos.size(); i++) {
                str += (i + 1) + "############\n" + new String(textos.get(i).getData(), codificacao.getCodificacao()) + "\n############";
            }
            byte[] x = ManipuladorDados.hexStringToByteArray(codificacao.getHexRepresentacao());
            byte[] y = str.getBytes(codificacao.getCodificacao());
            byte[] z = new byte[x.length + y.length];
            System.arraycopy(x, 0, z, 0, x.length);
            System.arraycopy(y, 0, z, x.length, y.length);
            FileOutputStream in = new FileOutputStream(arquivoEscolhido.getSelectedFile());
            in.write(z);
            in.close();
            diretorioCorrente = arquivoEscolhido.getCurrentDirectory();
            escreverArquivoConfigIni(diretorioCorrente.getAbsolutePath());
            System.out.println("Script extraído para o arquivo: " + arquivoEscolhido.getSelectedFile().getAbsolutePath());
        } else {
            throw new Exception("Operação de Extrair Script abortada.");
        }
    }

    public File abrirScript(TelaPrincipal form) throws Exception {
        File arquivo = null;
        FileFilter bmgFileFilter = new FileFilter() {
            @Override
            public boolean accept(File file) {
                return file.getAbsolutePath().endsWith(".txt") || file.isDirectory();
            }

            @Override
            public String getDescription() {
                return "Arquivo de Texto";
            }
        };
        JFileChooser arquivoEscolhido = new JFileChooser(diretorioCorrente);
        arquivoEscolhido.setDialogTitle("Abrir Script para Inserção");
        arquivoEscolhido.setFileFilter(bmgFileFilter);

        int returnVal = arquivoEscolhido.showOpenDialog(form);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            arquivo = arquivoEscolhido.getSelectedFile();
            diretorioCorrente = arquivoEscolhido.getCurrentDirectory();
            escreverArquivoConfigIni(diretorioCorrente.getAbsolutePath());
            System.out.println("Arquivo de Script aberto para inserção: " + arquivoEscolhido.getSelectedFile().getAbsolutePath());
        } else {
            throw new Exception("Operação de Abrir Script abortada.");
        }
        return arquivo;
    }

    public File salvarComo(TelaPrincipal form, File arquivoBmgCorrente, BmgFile bmgFile) throws Exception {
        File arquivo = null;
        JFileChooser arquivoEscolhido = new JFileChooser(diretorioCorrente) {
            @Override
            public void approveSelection() {
                File arquivo = getSelectedFile();
                if (arquivo.exists()) {
                    String msg = "\"{0}\" já existe.\nDeseja substituí-lo?";
                    msg = MessageFormat.format(msg, new Object[]{arquivo.getName()});
                    String title = "Confirmar Salvar como";
                    int option = JOptionPane.showConfirmDialog(this, msg, title, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
                    if (option == JOptionPane.NO_OPTION) {
                        return;
                    }
                }
                super.approveSelection();
            }
        };
        arquivoEscolhido.setFileFilter(new FileNameExtensionFilter("Arquivo BMG (*.bmg)", "bmg"));
        arquivoEscolhido.setDialogTitle("Salvar Aqruivo BMG");
        int returnVal = arquivoEscolhido.showSaveDialog(form);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            bmgFile.salvar(arquivoEscolhido.getSelectedFile());
            arquivo = arquivoEscolhido.getSelectedFile();
            diretorioCorrente = arquivoEscolhido.getCurrentDirectory();
            escreverArquivoConfigIni(diretorioCorrente.getAbsolutePath());
            System.out.println("Arquivo BMG Salvo Como: " + arquivoEscolhido.getSelectedFile().getAbsolutePath());
        } else {
            throw new Exception("Operação de Salvar Arquivo Como abortada.");
        }
        return arquivo;
    }

    public void salvar(File arquivoCorrente, BmgFile bmgFile) throws Exception {
        bmgFile.salvar(arquivoCorrente);
        System.out.println("Arquivo BMG Salvo: " + arquivoCorrente.getAbsolutePath());
    }

    public void salvarArquivo(TelaPrincipal form, BmgFile bmgFilePrincipal, ManipuladorArquivoService manipuladorArquivo, ConversorTexto parser, ICodificacao codificacao, File arquivoBmgCorrente, int index) {
        try {
            if (bmgFilePrincipal != null) {
                manipuladorArquivo.salvar(arquivoBmgCorrente, bmgFilePrincipal);
                if (parser != null) {
                    form.getTxtMessage().setText(parser.parseOutAllCodes(new String(bmgFilePrincipal.getDataTexto(index), codificacao.getCodificacao())));
                } else {
                    form.getTxtMessage().setText(new String(bmgFilePrincipal.getDataTexto(index), codificacao.getCodificacao()));
                }
                form.setTitle("Editor Arquivo BMG: " + arquivoBmgCorrente.getName());
            }
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
    }

    public void salvarArquivoComo(TelaPrincipal form, BmgFile bmgFilePrincipal, ManipuladorArquivoService manipuladorArquivo, ConversorTexto parser, ICodificacao codificacao, File arquivoBmgCorrente, int index) {
        try {
            if (bmgFilePrincipal != null) {
                arquivoBmgCorrente = salvarComo(form, arquivoBmgCorrente, bmgFilePrincipal);
                if (parser != null) {
                    form.getTxtMessage().setText(parser.parseOutAllCodes(new String(bmgFilePrincipal.getDataTexto(index), codificacao.getCodificacao())));
                } else {
                    form.getTxtMessage().setText(new String(bmgFilePrincipal.getDataTexto(index), codificacao.getCodificacao()));
                }
                form.setTitle("Editor Arquivo BMG: " + arquivoBmgCorrente.getName());
            }
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
    }
}
